<script setup lang="ts">
import type { ZodSchema } from 'zod'
import { computed, ref } from 'vue'
import { z } from 'zod'
import Eye from '@/components/icons/Eye.vue'
import KeyBoard from '@/components/icons/KeyBoard.vue'

const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
  type: {
    type: String,
    default: 'default',
    validator: (value: string) => ['phone', 'password', 'email', 'phone-email', 'default'].includes(value),
  },
  placeholder: {
    type: String,
    default: '',
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  schema: {
    type: Object as () => ZodSchema<any>,
    default: null,
  },
})

const emit = defineEmits(['update:modelValue', 'validationError', 'validationSuccess'])

const inputValue = computed({
  get: () => props.modelValue,
  set: value => emit('update:modelValue', value),
})

const inputType = computed(() => {
  return props.type === 'password' ? 'password' : 'text'
})

const showPassword = ref(false)
function togglePasswordVisibility() {
  showPassword.value = !showPassword.value
}

const effectiveInputType = computed(() => {
  if (props.type !== 'password')
    return inputType.value
  return showPassword.value ? 'text' : 'password'
})

// 处理电话号码前缀
const phonePrefix = ref('+86')

// 校验相关
const error = ref('')
const isValid = ref(true)
const showError = ref(false)
// 聚焦状态
const isFocused = ref(false)

// 执行校验
function validate() {
  if (!props.schema) {
    isValid.value = true
    error.value = ''
    return true
  }

  try {
    props.schema.parse(inputValue.value)
    isValid.value = true
    error.value = ''
    emit('validationSuccess')
    return true
  }
  catch (err) {
    if (err instanceof z.ZodError) {
      isValid.value = false
      error.value = err.errors[0]?.message || '输入无效'
      emit('validationError', error.value)
      showError.value = true
      return false
    }
    return true
  }
}

// 失去焦点时进行校验并显示错误
function handleBlur() {
  // 设置聚焦状态为false
  isFocused.value = false

  // 只在失去焦点时进行校验（懒校验）
  if (inputValue.value) {
    validate()
  }
  else {
    isValid.value = true
    error.value = ''
  }

  // 显示错误信息
  if (!isValid.value) {
    showError.value = true
  }
}

// 获得焦点时隐藏错误
function handleFocus() {
  isFocused.value = true
  showError.value = false
}

// 暴露给父组件的方法
defineExpose({
  validate,
  // 强制显示错误信息的方法
  forceValidate: () => {
    // 执行校验并返回结果
    const result = validate()
    // 强制显示错误信息
    showError.value = !isValid.value
    return result
  },
})
</script>

<template>
  <div class="auth-input-wrapper" :class="[type, { invalid: !isValid, focused: isFocused }]">
    <!-- 电话号码输入框 -->
    <div v-if="type === 'phone'" class="phone-input-container">
      <div class="prefix-container">
        <span>{{ phonePrefix }}</span>
        <div class="arrow-down" />
      </div>
      <input
        :type="effectiveInputType" :value="inputValue"
        :placeholder="placeholder" :disabled="disabled" class="auth-input"
        @input="e => inputValue = (e.target as HTMLInputElement).value" @blur="handleBlur" @focus="handleFocus"
      >
    </div>

    <!-- 邮箱输入框 -->
    <div v-else-if="type === 'email'" class="default-input-container">
      <input
        :type="effectiveInputType" :value="inputValue"
        :placeholder="placeholder" :disabled="disabled" class="auth-input"
        @input="e => inputValue = (e.target as HTMLInputElement).value" @blur="handleBlur" @focus="handleFocus"
      >
    </div>

    <!-- 手机号或邮箱输入框 -->
    <div v-else-if="type === 'phone-email'" class="default-input-container">
      <input
        :type="effectiveInputType" :value="inputValue"
        :placeholder="placeholder" :disabled="disabled" class="auth-input"
        @input="e => inputValue = (e.target as HTMLInputElement).value" @blur="handleBlur" @focus="handleFocus"
      >
    </div>

    <!-- 密码输入框 -->
    <div v-else-if="type === 'password'" class="password-input-container">
      <input
        :type="effectiveInputType" :value="inputValue"
        :placeholder="placeholder" :disabled="disabled" class="auth-input"
        @input="e => inputValue = (e.target as HTMLInputElement).value" @blur="handleBlur" @focus="handleFocus"
      >
      <KeyBoard class="input-icon" />
      <div class="password-toggle" @click="togglePasswordVisibility">
        <Eye :close="showPassword" class="eye" />
      </div>
    </div>

    <!-- 默认输入框 -->
    <div v-else class="default-input-container">
      <input
        :type="effectiveInputType" :value="inputValue"
        :placeholder="placeholder" :disabled="disabled" class="auth-input"
        @input="e => inputValue = (e.target as HTMLInputElement).value" @blur="handleBlur" @focus="handleFocus"
      >
    </div>

    <!-- 错误提示气泡 -->
    <div v-if="!isValid && showError" class="error-tooltip">
      {{ error }}
    </div>
  </div>
</template>

<style scoped>
.auth-input-wrapper {
  width: 100%;
  height: 50px;
  background-color: #f5f5f5;
  border-radius: 25px;
  overflow: visible;
  display: flex;
  align-items: center;
  margin-bottom: 16px;
  position: relative;
  transition: all 0.3s ease;
}

.auth-input-wrapper.invalid {
  background-color: #fff0f0;
  box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.3);
}

.auth-input-wrapper.focused {
  background-color: #f8f9ff;
  box-shadow: 0 0 0 2px var(--primary-color-100);
}

.auth-input {
  flex: 1;
  height: 100%;
  border: none;
  background: transparent;
  padding: 0 16px;
  font-size: 16px;
  outline: none;
}

.phone-input-container,
.password-input-container,
.default-input-container {
  display: flex;
  align-items: center;
  width: 100%;
  height: 100%;
}

.prefix-container {
  display: flex;
  align-items: center;
  padding: 0 16px;
  color: #333;
  font-size: 16px;
  cursor: pointer;
}

.arrow-down {
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid #333;
  margin-left: 5px;
}

.input-icon {
  margin-right: 16px;
  color: #666;
  width: 20px;
  height: 20px;
}

.password-toggle {
  margin-right: 16px;
  cursor: pointer;
  color: #666;
  position: relative;

  .eye {
    stroke: gray;
  }
}

.password-toggle:hover {
  color: #333;
}

.error-tooltip {
  position: absolute;
  bottom: -30px;
  left: 10px;
  background-color: #ff4d4f;
  color: white;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  z-index: 10;
  white-space: nowrap;
}

.error-tooltip::before {
  content: '';
  position: absolute;
  top: -6px;
  left: 10px;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid #ff4d4f;
}
</style>
